//! $Id$
//!
//! @file    Container.h
//! @author  Johan Andersson <skagget77@gmail.com>
//! @date    Sat Oct 03 14:41 2009
//! @ingroup IoCpp
//!

#if !defined(IOCPP_CONTAINER_H)
#define IOCPP_CONTAINER_H

#include "IoCpp/ConfigMacro.h"
#include "IoCpp/Injector.h"

namespace IoCpp
{
   //!
   //! @author  Johan Andersson <skagget77@gmail.com>
   //! @date    Sat Oct 03 14:41 2009
   //! @ingroup IoCpp
   //!
   //! The Container class.
   //!
   class IOCPP_API Container
   {
   public :
      //!
      //! Configures the container. This function should be called once before
      //! the container is used to inject instances, preferably in main.
      //!
      static void Configure();

      //!
      //! Returns the container's injector. The injector can be used to inject
      //! instances of types managed by the container.
      //!
      //! @return The container's injector.
      //!
      static const Injector& GetInjector();

   private :
      // Prevent instances.
      Container();
   };


   //!
   //! Injects an instance of the specified type.
   //!
   //! @return An instance of the specified type.
   //!
   template<class T1>
   T1 Inject() {
      return Container::GetInjector().Inject<T1>();
   };


   //!
   //! Injects an instance of the specified type. When the type matches more
   //! than one instance the name parameter is used to resolve which one to
   //! inject.
   //!
   //! @param  name A user defined name to resolve potential ambiguities.
   //!
   //! @return An instance of the specified type.
   //!
   template<class T1>
   T1 Inject( const std::string& name ) {
      return Container::GetInjector().Inject<T1>(name);
   }


namespace Detail 
{
   //!
   //! Configuration provider definition.
   //!
   typedef void (*ConfigProvider)(Configuration&);


   //!
   //! @author  Johan Andersson <skagget77@gmail.com>
   //! @date    Sat Oct 03 14:41 2009
   //! @ingroup IoCpp
   //!
   //! The RegisterConfiguration class.
   //!
   class IOCPP_API RegisterConfigProvider
   {
   public :
      //!
      //! Creates a new instance of the RegisterConfigProvider class.
      //!
      //! @param provider The configuration provider.
      //!
      RegisterConfigProvider( ConfigProvider provider );

   private :
      // Prevent copying.
      RegisterConfigProvider( const RegisterConfigProvider& );
      RegisterConfigProvider& operator=( const RegisterConfigProvider& );
   };
}
}

#endif   // IOCPP_CONTAINER_H
